#include "ZMO.h"


ZMO::ZMO(void)
{
	m_Channels = new LinkedList< Channel >();
	m_File = new FileHandler();
}


ZMO::~ZMO(void)
{
}

void ZMO::Load( char* a_FilePath )
{	
	m_File->LoadFile(  a_FilePath, "rb " );
	m_File->ReadFSTR( (char*)m_FormatCode, 8 );
	m_File->ReadInt( &m_FPS );
	m_File->ReadInt( &m_FrameCount );
	m_File->ReadInt( &m_ChannelCount );

	for ( int i = 0; i < m_ChannelCount; i++ )
	{
		Channel* NewChannel = new Channel();
		m_File->ReadInt( &NewChannel->m_Type );
		m_File->ReadInt( &NewChannel->m_TrackId );
		

		switch ( NewChannel->m_Type )
		{
		case POSITION:
			{
				NewChannel->m_Data = (char*) new Vector3[ m_FrameCount ];
			}
			break;
		case ROTATION:
			{
				NewChannel->m_Data = (char*) new Quaternion[ m_FrameCount ];
			}
			break;
		case NORMAL:
			{
				NewChannel->m_Data = (char*) new Vector3[ m_FrameCount ];
			}
			break;
		case ALPHA:
			{
				NewChannel->m_Data = (char*) new float[ m_FrameCount ];
			}
			break;
		case UV1:
			{
				NewChannel->m_Data = (char*)new Vector2[ m_FrameCount ];
			}
			break;
		case UV2:
			{
				NewChannel->m_Data = (char*)new Vector2[ m_FrameCount ];
			}
			break;
		case UV3:
			{
				NewChannel->m_Data = (char*)new Vector2[ m_FrameCount ];
			}
			break;
		case UV4:
			{
				NewChannel->m_Data = (char*)new Vector2[ m_FrameCount ];
			}
			break;
		case TEXTUREANIM:
			{
				NewChannel->m_Data = (char*)new float[ m_FrameCount ];
			}
			break;
		case SCALE:
			{
				NewChannel->m_Data = (char*)new float[ m_FrameCount ];
			}
			break;
		}
		
		m_Channels->AddFront( NewChannel );
	}

	m_ChannelIt = new Iterator< Channel >( m_Channels, 0 );

	for ( int i = 0; i < m_FrameCount; i++ )
	{
		if ( m_Channels->Length() != 0 )
		{	
			do 
			{
				switch( m_ChannelIt->CurrentNode()->m_Data->m_Type )
				{
					case POSITION:
					{
						Vector3* pos = (Vector3*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &pos[i].m_X );
						m_File->ReadFloat( &pos[i].m_Y );
						m_File->ReadFloat( &pos[i].m_Z );
						pos[i].m_X /= 100;
						pos[i].m_Y /= 100;
						pos[i].m_Z /= 100;
					}
					break;
					case ROTATION:
					{
						Quaternion* quad = (Quaternion*)m_ChannelIt->CurrentNode()->m_Data->m_Data;
						m_File->ReadFloat( &quad[i].m_S );
						m_File->ReadFloat( &quad[i].m_X );
						m_File->ReadFloat( &quad[i].m_Y );
						m_File->ReadFloat( &quad[i].m_Z );	
					}
					break;
					case NORMAL:
					{
						Vector3* pos = (Vector3*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &pos[i].m_X );
						m_File->ReadFloat( &pos[i].m_Y );
						m_File->ReadFloat( &pos[i].m_Z );
						pos[i].m_X /= 100;
						pos[i].m_Y /= 100;
						pos[i].m_Z /= 100;
					}
					break;
					case ALPHA:
					{
						float* alpha = (float*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &alpha[i] );
					}
					break;
					case UV1:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &pos[i].m_X );
						m_File->ReadFloat( &pos[i].m_Y );
						pos[i].m_X /= 100;
						pos[i].m_Y /= 100;
					}
					break;
					case UV2:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &pos[i].m_X );
						m_File->ReadFloat( &pos[i].m_Y );
						pos[i].m_X /= 100;
						pos[i].m_Y /= 100;
					}
					break;
					case UV3:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &pos[i].m_X );
						m_File->ReadFloat( &pos[i].m_Y );
						pos[i].m_X /= 100;
						pos[i].m_Y /= 100;
					}
					break;
					case UV4:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &pos[i].m_X );
						m_File->ReadFloat( &pos[i].m_Y );
						pos[i].m_X /= 100;
						pos[i].m_Y /= 100;
					}
					break;
					case TEXTUREANIM:
					{
						float* animation = (float*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &animation[i] );
					}
					break;
					case SCALE:
					{
						float* scale = (float*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->ReadFloat( &scale[i] );					
					}
					break;
				}
			} while ( m_ChannelIt->Loop() == true );
		}
	}

	m_File->Close();

}

void ZMO::Save( char* a_FilePath )
{
	m_File = new FileHandler();
	m_File->LoadFile( a_FilePath, "wb" );

	m_File->WriteFSTR( (char*)m_FormatCode, 8 );
	m_File->WriteInt( &m_FPS );
	m_File->WriteInt( &m_FrameCount );
	m_File->WriteInt( &m_ChannelCount );

	if ( m_ChannelCount != 0 )
	{
		do 
		{
			m_File->WriteInt( &m_ChannelIt->CurrentNode()->m_Data->m_Type );
			m_File->WriteInt( &m_ChannelIt->CurrentNode()->m_Data->m_TrackId );
		} while ( m_ChannelIt->Loop() );
	}

	for ( int i = 0; i < m_FrameCount; i++ )
	{
		if ( m_ChannelCount != 0 )
		{
			do 
			{
				switch( m_ChannelIt->CurrentNode()->m_Data->m_Type )
				{
				case POSITION:
					{
						Vector3* pos = (Vector3*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						pos[i].m_X *= 100;
						pos[i].m_Y *= 100;
						pos[i].m_Z *= 100;

						m_File->WriteFloat( &pos[i].m_X );
						m_File->WriteFloat( &pos[i].m_Y );
						m_File->WriteFloat( &pos[i].m_Z );					
					}
					break;
				case ROTATION:
					{
						Quaternion* quad = (Quaternion*)m_ChannelIt->CurrentNode()->m_Data->m_Data;
						m_File->WriteFloat( &quad[i].m_S );
						m_File->WriteFloat( &quad[i].m_X );
						m_File->WriteFloat( &quad[i].m_Y );
						m_File->WriteFloat( &quad[i].m_Z );	
					}
					break;
				case NORMAL:
					{
						Vector3* pos = (Vector3*)m_ChannelIt->CurrentNode()->m_Data->m_Data;
						
						pos[i].m_X *= 100;
						pos[i].m_Y *= 100;
						pos[i].m_Z *= 100;

						m_File->WriteFloat( &pos[i].m_X );
						m_File->WriteFloat( &pos[i].m_Y );
						m_File->WriteFloat( &pos[i].m_Z );						
					}
					break;
				case ALPHA:
					{
						float* alpha = (float*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->WriteFloat( &alpha[i] );
					}
					break;
				case UV1:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						pos[i].m_X *= 100;
						pos[i].m_Y *= 100;

						m_File->WriteFloat( &pos[i].m_X );
						m_File->WriteFloat( &pos[i].m_Y );
					}
					break;
				case UV2:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						pos[i].m_X *= 100;
						pos[i].m_Y *= 100;

						m_File->WriteFloat( &pos[i].m_X );
						m_File->WriteFloat( &pos[i].m_Y );
					}
					break;
				case UV3:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						pos[i].m_X *= 100;
						pos[i].m_Y *= 100;

						m_File->WriteFloat( &pos[i].m_X );
						m_File->WriteFloat( &pos[i].m_Y );
					}
					break;
				case UV4:
					{
						Vector2* pos = (Vector2*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						pos[i].m_X *= 100;
						pos[i].m_Y *= 100;

						m_File->WriteFloat( &pos[i].m_X );
						m_File->WriteFloat( &pos[i].m_Y );
					
					}
					break;
				case TEXTUREANIM:
					{
						float* animation = (float*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->WriteFloat( &animation[i] );
					}
					break;
				case SCALE:
					{
						float* scale = (float*)m_ChannelIt->CurrentNode()->m_Data->m_Data;

						m_File->WriteFloat( &scale[i] );					
					}
					break;
				}
			} while ( m_ChannelIt->Loop() );
		}
	}

	m_File->Close();

}

void ZMO::Show()
{
	if ( m_Channels->Length() != 0)
	{
		int count = 0;
		do 
		{
			if ( m_ChannelIt->CurrentNode()->m_Data->m_Type == POSITION )
			{
				printf(	"Channel %i [position]:\n", count );
				for ( int i = 0; i < m_FrameCount; i++ )
				{
					Vector3* pos = (Vector3*)m_ChannelIt->CurrentNode()->m_Data->m_Data;
					printf(	" X: %f, Y: %f, Z: %f\n", pos[i].m_X, pos[i].m_Y, pos[i].m_Z );
					pos[i].m_X -= .1;
					bool check = true;
				}				
			}

			if ( m_ChannelIt->CurrentNode()->m_Data->m_Type == ROTATION )
			{
				printf(	"Channel %i [rotation]:\n", count );
				for ( int i = 0; i < m_FrameCount; i += m_FPS )
				{
					Quaternion* quad = (Quaternion*)m_ChannelIt->CurrentNode()->m_Data->m_Data;
					printf(	"S: %f, X: %f, Y: %f, Z: %f\n", quad[i].m_S, quad[i].m_X, quad[i].m_Y, quad[i].m_Z );
					bool check = true;
				}
			}
			count++;
		} while ( m_ChannelIt->Loop() == true );
	}
}


